package cn.ac.radi.userver.waste.controller;

import cn.ac.radi.userver.model.wasteyard.minesafety.MineSafetyEvaluator;
import cn.ac.radi.userver.waste.constant.ResultStateConstant;
import cn.ac.radi.userver.waste.entity.*;
import cn.ac.radi.userver.waste.model.CoalSafetyModel;
import com.mathworks.toolbox.javabuilder.MWCharArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Paths;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.regex.Pattern;


@RestController
@RequestMapping("/model/4_4")
public class WasteController {

    @Autowired
    private Environment env;

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @GetMapping(value = "/tailing/version")
    public ResponseEntity<String> tailingPredict() throws  Exception{
        String version = "0.0.02";
        return new ResponseEntity<>(version, HttpStatus.OK);
    }

    /**
     * 日期选择
     * @param param
     * @return
     * @throws Exception
     */
    @PostMapping(value = "/coal/safety/date/select")
    public ResponseEntity<DateSelectResult> coalSaftyDateSelect(@RequestBody CoalSafetyDateSelectParam param) throws Exception{

        String uuid = generateUUID();
        //String uuid = this.generateUUID_test();
        Date start = param.getStart();
        Date end = param.getEnd();

        logger.info("[煤矿安全评估]：选择日期--开始--");
        logger.info("\t[Session]：" + uuid);

        boolean ret = true;
        CoalSafetyModel model = new CoalSafetyModel(this.env, this.logger);
        try{
            model.setUuid(uuid);
            ret = model.runDateSelect(start, end);
        }
        catch (Exception e){
            e.printStackTrace();
        }
        finally {
            DateSelectResult result = new DateSelectResult();
            if(ret){
                result.setUuid(uuid);
                result.setState(ResultStateConstant.SUCCESS);
            }
            else{
                result.setState(ResultStateConstant.FAILURE);
                result.setError(model.getErrorMessage());
            }


            logger.info("[煤矿安全评估]：选择日期--结束--");

            return new ResponseEntity<>(result, HttpStatus.OK);
        }
    }

    /**
     * 安全评估（水平位移、垂直位移、自燃风险）
     * @param params
     * @return
     * @throws Exception
     */
    @PostMapping(value = "/coal/safety/evaluate")
    public ResponseEntity<List<ValueProcessResult>> coalSafetyGDProcess(@RequestBody List<ValueProcessParam> params) throws Exception{

        CoalSafetyModel model = new CoalSafetyModel(this.env, this.logger);

        List<ValueProcessResult> results =  model.runEvaluates(params);

//        String DayGDFile ="H:/temp/gyy/11120/result/" + param.getFile();
//        int numReturns = 0;
//
//        MineSafetyEvaluator mse = null;
//        try{
//            mse = new MineSafetyEvaluator();
//            Object[] ret = mse.Value_GDprocess(DayGDFile);
//
//        }
//        catch (Exception e){
//            e.printStackTrace();
//        }
//        finally {
//            logger.info("安全评价：水平位移 Finish");
//        }

        String str = "Result";

        return new ResponseEntity<>(results, HttpStatus.OK);
    }


    /**
     * 安全评价：水平位移
     * Matlab函数：Value_GDprocess(DayGD)
     *       参数：DayGD->DayDPfile文件路径
     * @param
     * @return
     * @throws Exception
     */
//    @PostMapping(value = "/coal/safety/value/horizonal")
//    public ResponseEntity<String> coalSaftyGDProcess(@RequestBody CoalSafetyDateValueProcessParam param) throws Exception{
//
//        String DayGDFile ="H:/temp/gyy/11120/result/" + param.getFile();
//        int numReturns = 0;
//
//        MineSafetyEvaluator mse = null;
//        try{
//            mse = new MineSafetyEvaluator();
//            Object[] ret = mse.Value_GDprocess(DayGDFile);
//
//        }
//        catch (Exception e){
//            e.printStackTrace();
//        }
//        finally {
//            logger.info("安全评价：水平位移 Finish");
//        }
//
//        String str = "Result";
//
//        return new ResponseEntity<>(str, HttpStatus.OK);
//    }

    /**
     * 安全评价：垂直位移
     * Matlab函数：Value_DPprocess(DayGD)
     *       参数：DayGD->DayDPfile文件路径
     * @param
     * @return
     * @throws Exception
     */
//    @PostMapping(value = "/coal/safety/value/vertical")
//    public ResponseEntity<String> coalSaftyDPProcess(@RequestBody ValueProcessParam param) throws Exception{
//
//        String DayDPFile ="H:/temp/gyy/11120/result/" + param.getFile();
//        logger.info(DayDPFile);
//        int numReturns = 0;
//
//        MineSafetyEvaluator mse = null;
//        try{
//            mse = new MineSafetyEvaluator();
//            //Object[] ret = mse.Value_DPprocess(DayDPFile);
//            mse.Value_DPprocess(numReturns, DayDPFile);
//
//        }
//        catch (Exception e){
//            e.printStackTrace();
//        }
//        finally {
//            logger.info("安全评价：垂直位移 Finish");
//        }
//
//        String str = "Result";
//
//        return new ResponseEntity<>(str, HttpStatus.OK);
//    }

    /**
     * 安全评价：自燃风险
     * Matlab函数：Value_DPprocess(DayGD)
     *       参数：DayGD->DayDPfile文件路径
     * @param
     * @return
     * @throws Exception
     */
//    @PostMapping(value = "/coal/safety/value/burn")
//    public ResponseEntity<String> coalSaftyWDProcess(@RequestBody ValueProcessParam param) throws Exception{
//
//        String DayWDFile ="H:/temp/gyy/11120/result/" + param.getFile();
//        int numReturns = 0;
//
//        MineSafetyEvaluator mse = null;
//        try{
//            mse = new MineSafetyEvaluator();
//            Object[] ret = mse.Value_WDprocess(DayWDFile);
//
//        }
//        catch (Exception e){
//            e.printStackTrace();
//        }
//        finally {
//            logger.info("安全评价：自燃风险 Finish");
//        }
//
//        String str = "Result";
//
//        return new ResponseEntity<>(str, HttpStatus.OK);
//    }

    /**
     * 预警级别分析
     * @param param
     * @return
     * @throws Exception
     */
    @PostMapping(value = "/coal/safety/earlywarning/level")
    public ResponseEntity<EarlyWarningLevelResult> coalSaftyEarlyWarningLevel(@RequestBody EarlyWarningLevelParam param) throws Exception{

        String uuid = param.getUuid();
        float gd_v = param.getGdV();
        float gd_detv = param.getGdDetv();
        float gd_alpha = param.getGdAlpha();
        float dp_s = param.getDpS();
        float wd_max = param.getWdMax();

        logger.info("\t安全等级评估: ");
        logger.info("\t[SessionID]: "+uuid);

        String output_path = env.getProperty("userver.model.4_4.coal_safety.output");

        int numReturns = 3;

        EarlyWarningLevelResult result = new EarlyWarningLevelResult();

        MineSafetyEvaluator mse = null;
        try{
            mse = new MineSafetyEvaluator();
            Object[] objs = mse.EarlyWarningLevel(numReturns, gd_v, gd_detv, gd_alpha, dp_s, wd_max, output_path, uuid);
            if(objs.length==numReturns){
                MWCharArray arr = (MWCharArray)(objs[0]);
                String level = arr.toString();
                logger.info("[水平预警级别]：" + level);
                result.setLevelGD(level);

                arr = (MWCharArray)(objs[1]);
                level = arr.toString();
                logger.info("[沉降预警级别]：" + level);
                result.setLevelDP(level);

                arr = (MWCharArray)(objs[2]);
                level = arr.toString();
                logger.info("[沉降预警级别]：" + level);
                result.setLevelWD(level);
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
        finally {
            logger.info("安全评价：自燃风险 Finish");
        }
        return new ResponseEntity<>(result, HttpStatus.OK);
    }

    /**
     * 生成报表
     * @param param
     * @return
     * @throws Exception
     */
    @PostMapping(value = "/coal/safety/createReport")
    public ResponseEntity<ModelRunResult> coalSaftyCreateReport(@RequestBody CreateReportParam param) throws Exception{

        String uuid = param.getUuid();

        logger.info("\t生成安全评估报表: ");
        logger.info("\t[SessionID]: "+uuid);

        long st = System.currentTimeMillis();

        ModelRunResult result = new ModelRunResult();
        CoalSafetyModel model = new CoalSafetyModel(this.env, this.logger);
        model.setUuid(uuid);
        boolean ret = model.runCreateReport();
        if(ret){
            result.setState(ResultStateConstant.SUCCESS);
            result.setUrl(model.getReportWebPath());
        }
        else{
            result.setState(ResultStateConstant.FAILURE);
        }

        long et = System.currentTimeMillis();
        logger.info("\t生成安全评估报表运行时间: " + Long.toString(et-st) + " 秒");

        return new ResponseEntity<>(result, HttpStatus.OK);

//        //String input = param.getInput();
//        String input = "H:\\temp\\gyy\\11120\\result";
//        String output = "H:\\temp\\gyy\\11120\\report";
//
//        int numReturns = 1;
//
//        EarlyWarningLevelResult result = new EarlyWarningLevelResult();
//
//        MineSafetyEvaluator mse = null;
//        try{
//            mse = new MineSafetyEvaluator();
//            mse.creatReport(input, output);
//        }
//        catch (Exception e){
//            e.printStackTrace();
//        }
//        finally {
//            logger.info("安全评价：生成报表 Finish");
//        }
//        String str = "dfdfsdf";
//        return new ResponseEntity<>(str, HttpStatus.OK);
    }
//    @PostMapping(value = "/coal/safety/createReport")
//    public ResponseEntity<String> coalSaftyCreateReport(@RequestBody CreateReportParam param) throws Exception{
//
//        //String input = param.getInput();
//        String input = "H:\\temp\\gyy\\11120\\result";
//        String output = "H:\\temp\\gyy\\11120\\report";
//
//        int numReturns = 1;
//
//        EarlyWarningLevelResult result = new EarlyWarningLevelResult();
//
//        MineSafetyEvaluator mse = null;
//        try{
//            mse = new MineSafetyEvaluator();
//            mse.creatReport(input, output);
//        }
//        catch (Exception e){
//            e.printStackTrace();
//        }
//        finally {
//            logger.info("安全评价：生成报表 Finish");
//        }
//        String str = "dfdfsdf";
//        return new ResponseEntity<>(str, HttpStatus.OK);
//    }

    @GetMapping(value = "/version")
    public ResponseEntity<String> version() throws Exception{
        String version = "3.2.1";
        return new ResponseEntity<>(version, HttpStatus.OK);
    }

    @GetMapping(value = "/python")
    public ResponseEntity<String> runPython() throws Exception{

        logger.info("~~~~~~~~~~~~ run python begin ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");

        String cmd = "source activate &";
        cmd += "conda activate /cache/conda_envs/py36_torch_120 &";
        cmd += "python newFile.py ";

        logger.info(cmd);

        String homePath = "/home/geobeans/code/python";
        runCommandProcess(cmd, homePath, logger);

        logger.info("~~~~~~~~~~~~ run python end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");

        String version = "test";
        return new ResponseEntity<>(version, HttpStatus.OK);
    }

    private boolean runCommandProcess(String cmd, String homePath, Logger logger){

        logger.info("\t[python命令]：" + cmd);
        logger.info("\t[python home]：" + homePath);

        long ts = System.currentTimeMillis();   //获取开始时间

        logger.debug("~~~~~~~~~开始~~~~~~~~");

        boolean ret = false;
        Process proc = null;
        try{
            Runtime rt = Runtime.getRuntime();
            proc = rt.exec(cmd, null, new File(homePath));

            writeProcessStream(proc);

            ret = true;

            proc.waitFor();
        }
        catch (IOException e){
            e.printStackTrace();
        }
        catch (RuntimeException e){
            e.printStackTrace();
        }
        catch (InterruptedException e){
            e.printStackTrace();
        }
        finally {

            logger.debug("~~~~~~~~~结束~~~~~~~~");

            long te = System.currentTimeMillis();   //获取结束时间
            logger.info("运行时间：" + Long.toString(te-ts) + " 毫秒");

            if(proc!=null){
                logger.info("~~~~~~~~销毁processor~~~~~~~~");
                proc.destroy();
            }

            return ret;
        }
    }

    private void writeProcessStream(Process proc){

        BufferedReader br=null;
        BufferedReader bo=null;
        BufferedReader be=null;
        String line = null;

        try{
            br=new BufferedReader(
                    new InputStreamReader(
                            proc.getInputStream()
                    )
            );

            while((line=br.readLine())!=null){
                logger.info(line);
            }

            be=new BufferedReader(
                    new InputStreamReader(
                            proc.getErrorStream()
                    )
            );
            while((line=be.readLine())!=null){
                logger.info(line);
            }

//            bo=new BufferedReader(
//                    new OutputStream(
//                            proc.getOutputStream()
//                    )
//            );
//            while((line=bo.readLine())!=null){
//                logger.info(line);
//            }
        }
        catch (IOException e){
            e.printStackTrace();
        }
    }

    private String generateUUID(){
        String pattern = "[^0-9].*";
        String uuid = UUID.randomUUID().toString();
        while (!Pattern.matches(pattern,uuid)){
            uuid = UUID.randomUUID().toString();
        }
        return uuid;
    }

    private String generateUUID_test(){
        return "202201042017";
    }

}
